package com.ljk.util.pdf.template;

import com.fasterxml.jackson.databind.JsonNode;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.ljk.util.array.CollectionUtil;
import com.ljk.util.jackson.JsonUtil;
import com.ljk.util.pdf.PdfUtil;
import com.ljk.util.pdf.PrescriptionType;
import com.ljk.util.pdf.data.*;
import com.ljk.util.string.StringUtil;

import java.io.OutputStream;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

import static com.ljk.util.pdf.PdfUtil.createCell;
import static com.ljk.util.pdf.PdfUtil.parseOneCell;

public class PdfTemplate4Bl implements PdfTemplate<MedicalRecordEntity> {

    @Override
    public void generatePdf(OutputStream os, MedicalRecordEntity bean) throws DocumentException {
        MedicalRecordData data = bean.getData();
        MedicalRecordStyle style = bean.getStyle();
        BlType blType = data.getBlType();
        if (blType == null) {
            blType = BlType.MZ;
        }
        final BaseFont baseFont = PdfUtil.getBaseFont();
        // 创建PDF文档
        Document document = new Document(PageSize.A4);
        document.setMargins(10, 10, 10, 30);

        // 创建PDF写入器
        PdfWriter writer = PdfWriter.getInstance(document, os);
        writer.setPageEvent(new PageNumberEvent(10, document.getPageSize()));
        // 打开文档
        document.open();

        //文档的具体坐标
        float docWidth = document.right() - document.left();//可用宽度
        float docHeight = document.top() - document.bottom();//可用高度
        float leftMargin = document.leftMargin();//左边距
        float rightMargin = document.rightMargin();//右边距
        float topMargin = document.topMargin();//上边距
        float bottomMargin = document.bottomMargin();//下边距
        //获取画板
        PdfContentByte cb = writer.getDirectContent();
        Font font = new Font(baseFont, 12, Font.NORMAL);

        // 设置画板内头部的坐标和大小
        float height = 73.6f;
        float width = docWidth;
        float x = document.left();
        float y = docHeight - height;

//        cb.rectangle(x, y, width, height);
//        cb.stroke();

        // 在画板内绘制一些内容
        cb.beginText();
        cb.setFontAndSize(baseFont, 15);
        cb.setCharacterSpacing(2);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, StringUtil.nvl(data.getDeptName(), ""), x + width / 2, y + height + 10, 0);

        String signNo = data.getSignNo();
        if (signNo != null) {
            cb.setCharacterSpacing(0);
            cb.setFontAndSize(baseFont, 8);
            cb.showTextAligned(PdfContentByte.ALIGN_RIGHT, "电子签名签署编号:  ", x + width / 2 - 50, y + height / 2f + 30, 0);
            cb.setFontAndSize(baseFont, 12);
            cb.showTextAligned(PdfContentByte.ALIGN_LEFT, signNo, x + width / 2 - 50, y + height / 2f + 10, 0);

        }
        cb.setFontAndSize(baseFont, 32);
        cb.setCharacterSpacing(9.2f);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, StringUtil.nvl(data.getTitle(), ""), x + width / 2, y + 20 / 2f +20, 0);
        cb.setCharacterSpacing(0);
        cb.endText();

        PdfUtil.createBlank(document, height + topMargin);

        PdfPTable headTable = new PdfPTable(1);
        headTable.setWidthPercentage(100);

        Font keyFont = new Font(baseFont, 10, Font.NORMAL);
        {
            String l1c2K = blType == BlType.MZ ? "费别" : "医师";
            String l1c2V = blType == BlType.MZ ? data.getSettleType() : data.getDoctorName();
            String l1c3K = blType == BlType.MZ ? "门诊号" : "住院号";
            String l1c3V = data.getInHospNo();

            PdfPCell cell1 = PdfUtil.parseOneCell(new float[]{19, 33}, PdfUtil.createCell(keyFont, "定点医疗机构编号", Element.ALIGN_LEFT), PdfUtil.createCell(font, data.getMedicalInsuranceCode(), Element.ALIGN_LEFT));
            PdfPCell cell2 = PdfUtil.parseOneCell(new float[]{6, 24}, PdfUtil.createCell(keyFont, l1c2K, Element.ALIGN_CENTER), PdfUtil.createCell(font, l1c2V, Element.ALIGN_LEFT));
            PdfPCell cell3 = PdfUtil.parseOneCell(new float[]{10, 11}, PdfUtil.createCell(keyFont, l1c3K, Element.ALIGN_RIGHT), PdfUtil.createCell(font, l1c3V, Element.ALIGN_CENTER));
            PdfPCell cell = PdfUtil.parseOneCell(new float[]{54, 37, 37}, cell1, cell2, cell3);
            cell.setBorder(Rectangle.BOTTOM);
            cell.setPaddingBottom(3);
            headTable.addCell(cell);
        }
        {
            PdfPCell cell1 = PdfUtil.parseOneCell(new float[]{6, 20}, PdfUtil.createCell(keyFont, "姓名", Element.ALIGN_LEFT), PdfUtil.createCell(font, data.getPatientName(), Element.ALIGN_LEFT));
            PdfPCell cell2 = PdfUtil.parseOneCell(new float[]{6, 14}, PdfUtil.createCell(keyFont, "性别", Element.ALIGN_CENTER), PdfUtil.createCell(font, data.getSex(), Element.ALIGN_LEFT));
            PdfPCell cell3 = PdfUtil.parseOneCell(new float[]{6, 20}, PdfUtil.createCell(keyFont, "年龄", Element.ALIGN_CENTER), PdfUtil.createCell(font, data.getAge(), Element.ALIGN_LEFT));
            PdfPCell cell4 = PdfUtil.parseOneCell(new float[]{9, 40}, PdfUtil.createCell(keyFont, "个人编号", Element.ALIGN_RIGHT), PdfUtil.createCell(font, data.getPsnNo(), Element.ALIGN_LEFT));
            PdfPCell cell = PdfUtil.parseOneCell(new float[]{26, 18, 26, 50}, cell1, cell2, cell3, cell4);
            cell.setBorder(Rectangle.BOTTOM);
            cell.setPaddingBottom(3);
            headTable.addCell(cell);
        }

        {
            String l3c3K = blType == BlType.MZ ? "联系方式" : "结算类别";
            String l3c3V = blType == BlType.MZ ? data.getPhone() : data.getSettleType();
            String l2c2K = blType == BlType.MZ ? "身份证号" : "证件号";

            PdfPCell cell1 = PdfUtil.parseOneCell(new float[]{9, 25}, PdfUtil.createCell(keyFont, "就诊科室", Element.ALIGN_LEFT), PdfUtil.createCell(font, data.getSectionName(), Element.ALIGN_LEFT));
            PdfPCell cell2 = PdfUtil.parseOneCell(new float[]{10, 36}, PdfUtil.createCell(keyFont, l2c2K, Element.ALIGN_CENTER), PdfUtil.createCell(font, data.getIdNo(), Element.ALIGN_LEFT));
            PdfPCell cell3 = PdfUtil.parseOneCell(new float[]{9, 28}, PdfUtil.createCell(keyFont, l3c3K, Element.ALIGN_CENTER), PdfUtil.createCell(font, l3c3V, Element.ALIGN_LEFT));
            PdfPCell cell = PdfUtil.parseOneCell(new float[]{34, 46, 37}, cell1, cell2, cell3);
            cell.setBorder(Rectangle.BOTTOM);
            cell.setPaddingBottom(3);
            headTable.addCell(cell);
        }

        headTable.addCell(PdfUtil.createBankCell(15));
        document.add(headTable);

        PdfPTable textTable = new PdfPTable(new float[]{17, 83});
        textTable.setWidthPercentage(93);
        textTable.addCell(PdfUtil.createCell(font, "就诊时间：", Element.ALIGN_RIGHT));
        textTable.addCell(PdfUtil.createCell(font, data.getCreateTime(), Element.ALIGN_LEFT));

        if (!CollectionUtil.isEmpty(data.getDetail())) {
            List<MedicalRecordStyleDetail> styleItemList = style.getItemList();
            for (MedicalRecordStyleDetail it : styleItemList) {
                if (it.getOrderNum() == null) {
                    it.setOrderNum(99);
                }
            }
            styleItemList.sort(Comparator.comparing(MedicalRecordStyleDetail::getOrderNum));
            Map<String, MedicalDetailBo> deatilMap = data.getDetail().stream().collect(Collectors.toMap(MedicalDetailBo::getElementCode, v -> v));
            for (MedicalRecordStyleDetail styleItem : styleItemList) {
                MedicalDetailBo detail = deatilMap.get(styleItem.getElementCode());
                if (detail == null || detail.getElementText() == null) {
                    continue;
                }
                String labelName = StringUtil.nvl(detail.getLabelName(), styleItem.getLabelName());
                String boxDataType = StringUtil.nvl(styleItem.getBoxDataType(), "");
                Object elementText = detail.getElementText();
                String labelValue = null;
                List<PdfPCell> labelValueList = Collections.emptyList();
                switch (boxDataType) {
                    case "string":
                        labelValue = (String) elementText;
                        break;
                    case "integer":
                        labelValue = String.valueOf(elementText);
                        break;
                    case "toothArray"://[{"text": "龋坏近髓", "tooth": {"1": [], "2": [], "3": [6], "4": []}}]
                    case "toothDiag"://[{"text": "牙位：;内容：牙龈炎", "tooth": {"1": [], "2": [], "3": [], "4": []}}]
                        JsonNode toothArrayNode = JsonUtil.parseJson(String.valueOf(elementText));
                        if (toothArrayNode.isEmpty()) {
                            continue;
                        }
                        labelValueList = new ArrayList<>(toothArrayNode.size() + 1);
                        for (JsonNode toothNode : toothArrayNode) {
                            String tooth = JsonUtil.findNode2Str(toothNode, "text");
                            if (StringUtil.isNotEmpty(tooth)) {
                                labelValueList.add(PdfUtil.createCell(font, tooth, Element.ALIGN_LEFT));
                            }
                        }
                        if (labelValueList.isEmpty()) {
                            labelValue = "";
                        }
                        break;
                    case "toothYbDiag":
                    case "photoArray":
                    default:
                        continue;
                }
                textTable.addCell(PdfUtil.createCell(font, labelName + "：", Element.ALIGN_RIGHT));
                if (labelValue != null) {
                    textTable.addCell(PdfUtil.createCell(font, labelValue, Element.ALIGN_LEFT));
                } else {
                    if (labelValueList.size()==1){
                        textTable.addCell(labelValueList.get(0));
                    }else {
                        textTable.addCell(PdfUtil.parseOneCell(new float[]{1},labelValueList));
                    }
                }
            }
        }

        textTable.addCell(PdfUtil.createCell(font, "诊断：", Element.ALIGN_TOP, Element.ALIGN_RIGHT));
        if (CollectionUtil.isEmpty(data.getDiagnosisList())) {
            textTable.addCell(PdfUtil.createBankCell());
        } else {
            PdfPTable diagTable = new PdfPTable(1);
            Map<Integer, List<MedicalRecordDiagnosis>> diagMap = data.getDiagnosisList().stream().collect(Collectors.groupingBy(MedicalRecordDiagnosis::getDiagClass));
            List<MedicalRecordDiagnosis> xyDiagList = diagMap.get(1);
            List<MedicalRecordDiagnosis> zyDiagList = diagMap.get(3);
            List<MedicalRecordDiagnosis> writeDiagList = diagMap.get(0);
            List<MedicalRecordDiagnosis> list = new ArrayList<>((writeDiagList != null ? writeDiagList.size() : 0) + (xyDiagList != null ? xyDiagList.size() : 0) + 1);

            if (xyDiagList!=null){
                list.addAll(xyDiagList);
            }
            if (writeDiagList!=null) {
                list.addAll(writeDiagList);
            }
            boolean hasDiag = false;
            if (!list.isEmpty()) {
                hasDiag = true;
                StringJoiner xyJoiner = new StringJoiner(";", "西医诊断：", "");
                for (MedicalRecordDiagnosis diag : list) {
                    xyJoiner.add(diag.getDiagnosisName());
                }
                diagTable.addCell(PdfUtil.createCell(font, xyJoiner.toString(), Element.ALIGN_LEFT));
            }
            if (zyDiagList != null) {
                hasDiag = true;
                StringJoiner zyJoiner = new StringJoiner(";", "中医诊断：", "");
                for (MedicalRecordDiagnosis diag : zyDiagList) {
                    String diagnosisName = diag.getDiagnosisName();
                    if (StringUtil.isNotEmpty(diag.getDiagRemark())) {
                        diagnosisName += "(" + StringUtil.nvl(diag.getDiagRemark(), "") + ")";
                    }
                    zyJoiner.add(diagnosisName);
                }
                diagTable.addCell(PdfUtil.createCell(font, zyJoiner.toString(), Element.ALIGN_LEFT));
            }
            if (!hasDiag) {
                diagTable.addCell(PdfUtil.createBankCell());
            }
            textTable.addCell(PdfUtil.parseCell4Table(diagTable));
        }

        if (StringUtil.isNotEmpty(data.getDialecticalBasis())){
            textTable.addCell(PdfUtil.createCell(font, "辨病辨证依据：", Element.ALIGN_TOP,Element.ALIGN_RIGHT));
            textTable.addCell(PdfUtil.createCell(font, data.getDialecticalBasis(), Element.ALIGN_LEFT));
        }

        List<PdfPCell> presCellList = new ArrayList<>();//所有处方的表格列表
        //组装处方列表
        {
            List<Prescription4Bl> itemIdeaList = data.getItemIdeaList();
            Map<String, List<Prescription4Bl>> prescriptionMap = itemIdeaList.stream().collect(Collectors.groupingBy(Prescription4Bl::getPrescriptionType));
            int itemCount = 0;
            //中草药
            List<Prescription4Bl> zyIdea;
            if (blType == BlType.LTC) {
                //2 长护中药
                zyIdea = prescriptionMap.remove(PrescriptionType.INJECTION);
            } else {
                // 4 门诊中药处方
                // 9 中药配方颗粒处方笺
                List<Prescription4Bl> zy4 = prescriptionMap.remove(PrescriptionType.CHINESE_DRUG);
                List<Prescription4Bl> zy9 = prescriptionMap.remove(PrescriptionType.CHINESE_DRUG_PARTICLE);
                zyIdea = new ArrayList<>();
                if (zy4 != null) {
                    zyIdea.addAll(zy4);
                }
                if (zy9 != null) {
                    zyIdea.addAll(zy9);
                }
            }
            float[] itemRelativeWidths = {5, 110};

            if (!CollectionUtil.isEmpty(zyIdea)) {
                float[] zyRelativeWidths = {13, 5};
                Font smallFont = new Font(baseFont, 6, Font.NORMAL);
                itemCount++;
                String cureRule = StringUtil.nvl(data.getCureRule(), "");
                presCellList.add(PdfUtil.parseOneCell(itemRelativeWidths, PdfUtil.createCell(font, itemCount + ".", Element.ALIGN_LEFT), PdfUtil.createCell(font, "治则：" + cureRule, Element.ALIGN_LEFT)));
                int zyIdx = 0;
                for (Prescription4Bl zyPres : zyIdea) {
                    if (CollectionUtil.isEmpty(zyPres.getDetailList())) {
                        continue;
                    }
                    presCellList.add(PdfUtil.createCell(font, String.format("（%d）中草药：", ++zyIdx), Element.ALIGN_LEFT));
                    ArrayList<PdfPCell> zyItemCellList = new ArrayList<>(zyPres.getDetailList().size() + 3);
                    for (PrescriptionItem item : zyPres.getDetailList()) {
                        String itemName = StringUtil.nvl(item.getItemName(), "");
                        String fryingTypeStr = item.getFryingType();
                        String quantity = StringUtil.nvl(item.getQuantity(), "") + StringUtil.nvl(item.getQuantityUnit(), "");

                        PdfPCell cellLeft = new PdfPCell();
                        if (StringUtil.isNotEmpty(fryingTypeStr)) {
                            PdfDiv pdfDiv = new PdfDiv();
                            pdfDiv.addElement(new Chunk(fryingTypeStr, smallFont));
                            pdfDiv.setPaddingTop(-3);
                            pdfDiv.setPaddingBottom(-5);
                            if (StringUtil.isNotEmpty(fryingTypeStr)) {
                                int rightLength = 71 - fryingTypeStr.length() * 7;
                                int leftLength = (int) baseFont.getWidthPoint(itemName, 12);
                                if (leftLength > rightLength) {
                                    leftLength = rightLength;
                                }
                                pdfDiv.setPaddingLeft(leftLength);
                            }
                            cellLeft.addElement(pdfDiv);
                        }
                        PdfDiv fryingDiv = new PdfDiv();
                        fryingDiv.addElement(new Chunk(itemName, font));
                        cellLeft.addElement(fryingDiv);
                        cellLeft.setBorder(Rectangle.NO_BORDER);
                        PdfPCell cell = parseOneCell(zyRelativeWidths, cellLeft, createCell(font, quantity, Element.ALIGN_BOTTOM, Element.ALIGN_LEFT));
                        zyItemCellList.add(cell);
                    }
                    PdfPTable zyTable = new PdfPTable(4);
                    zyTable.setWidthPercentage(95);
                    int autoCount = zyItemCellList.size() % 4;
                    if (autoCount != 0) {
                        PdfPCell cell = PdfUtil.createBankCell();
                        autoCount = 4 - autoCount;
                        for (int i = 0; i < autoCount; i++) {
                            zyItemCellList.add(cell);
                        }
                    }
                    zyItemCellList.forEach(zyTable::addCell);
                    presCellList.add(PdfUtil.parseCell(zyTable));
                    if (StringUtil.isNotEmpty(zyPres.getUsageStr())) {
                        presCellList.add(PdfUtil.createCell(font, "  " + zyPres.getUsageStr(), Element.ALIGN_LEFT));
                    }
                }
            }
            //检查检验
            List<Prescription4Bl> itemCheckList = data.getItemCheckList();
            if (!CollectionUtil.isEmpty(itemCheckList)) {
                for (Prescription4Bl pres : itemCheckList) {
                    if (CollectionUtil.isEmpty(pres.getDetailList())) {
                        continue;
                    }
//                    PdfPTable checkTable = new PdfPTable(1);
                    List<PrescriptionItem> detailList = pres.getDetailList();
                    for (PrescriptionItem item : detailList) {
                        itemCount++;
                        //打印套餐明细
                        List<PrescriptionItemPackageDetail> packageDetailList = item.getPackageDetailList();
                        if (item.getIfPrintTcmx() != null && item.getIfPrintTcmx() == 1 && !CollectionUtil.isEmpty(packageDetailList)) {
                            for (int i = 0; i < packageDetailList.size(); i++) {
                                PdfPCell seqCell = i==0?createCell(font, itemCount + ".", Element.ALIGN_TOP, Element.ALIGN_LEFT):PdfUtil.createBankCell();
                                PrescriptionItemPackageDetail packageDetail = packageDetailList.get(i);
                                String str = StringUtil.nvl(packageDetail.getItemName(), "") + " " + StringUtil.nvl(packageDetail.getQuantity(), "") + StringUtil.nvl(packageDetail.getQuantityUnit(), "") + "。";
                                presCellList.add(PdfUtil.parseOneCell(itemRelativeWidths, seqCell, PdfUtil.createCell(font, str, Element.ALIGN_LEFT)));
                            }
                        }else {
                            //打印本身
                            PdfPCell seqCell = createCell(font, itemCount + ".", Element.ALIGN_TOP, Element.ALIGN_LEFT);
                            String str = StringUtil.nvl(item.getItemName(), "") + " " + StringUtil.nvl(item.getQuantity(), "") + StringUtil.nvl(item.getQuantityUnit(), "") + "。";
                            presCellList.add(PdfUtil.parseOneCell(itemRelativeWidths, seqCell, PdfUtil.createCell(font, str, Element.ALIGN_LEFT)));
                        }
                    }
                }
            }
            //其他药品
            for (Map.Entry<String, List<Prescription4Bl>> presListEntry : prescriptionMap.entrySet()) {
                for (Prescription4Bl pres : presListEntry.getValue()) {
                    if (CollectionUtil.isEmpty(pres.getDetailList())) {
                        continue;
                    }
                    List<PrescriptionItem> detailList = pres.getDetailList();
                    itemCount++;
                    PdfPTable ideaTable = new PdfPTable(1);
                    for (PrescriptionItem item : detailList) {
                        StringJoiner sj = new StringJoiner("，");
                        if (StringUtil.isNotEmpty(item.getItemName())) {
                            sj.add(item.getItemName());
                        }
                        if (StringUtil.isNotEmpty(item.getSpec())) {
                            sj.add(item.getSpec());
                        }
                        String quantity = StringUtil.nvl(item.getQuantity(), "") + StringUtil.nvl(item.getQuantityUnit(), "");
                        if (StringUtil.isNotEmpty(quantity)) {
                            sj.add(quantity);
                        }
                        if (StringUtil.isNotEmpty(item.getUsageType())) {
                            sj.add(item.getUsageType());
                        }
                        String dose = StringUtil.nvl(item.getDose(), "") + StringUtil.nvl(item.getDoseUnit(), "");
                        if (StringUtil.isNotEmpty(dose)) {
                            sj.add(dose);
                        }
                        if (item.getMedicationDay() != null) {
                            sj.add(item.getMedicationDay() + "天");
                        }
                        if (StringUtil.isNotEmpty(item.getFrequencyName())) {
                            sj.add(item.getFrequencyName());
                        }
                        if (StringUtil.isNotEmpty(item.getRemark())) {
                            sj.add(item.getRemark());
                        }
                        String sjs = sj.toString();
                        ideaTable.addCell(PdfUtil.createCell(font, sjs + "。", Element.ALIGN_LEFT));
                    }
                    PdfPCell seqCell = createCell(font, itemCount + ".", Element.ALIGN_TOP, Element.ALIGN_LEFT);
                    presCellList.add(PdfUtil.parseOneCell(itemRelativeWidths, seqCell, PdfUtil.parseCell4Table(ideaTable)));
                }
            }
        }

        for (int i = 0; i < presCellList.size(); i++) {
            if (i==0){
                textTable.addCell(PdfUtil.createCell(font, "治疗意见：", Element.ALIGN_TOP, Element.ALIGN_RIGHT));
            }else {
                textTable.addCell(PdfUtil.createBankCell());
            }
            PdfPCell presCell = presCellList.get(i);
            textTable.addCell(presCell);
        }

        if (StringUtil.isNotEmpty(data.getOtherOrderRemark())) {
            textTable.addCell(PdfUtil.createCell(font, "其他嘱托：", Element.ALIGN_RIGHT));
            textTable.addCell(PdfUtil.createCell(font, data.getOtherOrderRemark(), Element.ALIGN_LEFT));
        }
        document.add(textTable);

        PdfUtil.createBlank(document, 50);

        PdfPTable signTable = new PdfPTable(1);
        signTable.setWidthPercentage(90);

        PdfPCell doctorK = PdfUtil.createCell(font, "医生签名", Element.ALIGN_RIGHT);
        PdfPCell doctorV;
        List<SignData> doctorList = data.getDoctorList();
        if (CollectionUtil.isEmpty(doctorList)) {
            doctorV = PdfUtil.createCell(font, "", Element.ALIGN_CENTER);
            signTable.addCell(parseOneCell(new float[]{400, 50}, doctorK, doctorV));
        } else if (doctorList.size() == 1) {
            doctorV = PdfUtil.createSignCell(font, doctorList.get(0));
            signTable.addCell(parseOneCell(new float[]{400, 50}, doctorK, doctorV));
        } else {
            SignData signData1 = doctorList.get(0);
            SignData signData2 = doctorList.get(1);
            PdfPCell cell1 = PdfUtil.createSignCell(font, signData1);
            PdfPCell cell2 = PdfUtil.createSignCell(font, signData2);
            cell1.setHorizontalAlignment(Element.ALIGN_RIGHT);
            cell2.setHorizontalAlignment(Element.ALIGN_LEFT);
            if (signData1.getType() == SignType.string) {
                doctorV = PdfUtil.parseOneCell(new float[]{10, 2, 10}, cell1, PdfUtil.createCell(font, "/", Element.ALIGN_CENTER), cell2);
                signTable.addCell(parseOneCell(new float[]{330, 70}, doctorK, doctorV));
            } else {
                doctorV = PdfUtil.parseOneCell(cell1, cell2);
                doctorV.setFixedHeight(25);
                signTable.addCell(parseOneCell(new float[]{290, 100}, doctorK, doctorV));
            }
        }
        document.add(signTable);

        // 关闭文档
        document.close();
    }


}
